package com.itbaizhan.service;

import com.itbaizhan.dao.AccountDao;
import com.itbaizhan.domain.Account;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
//使用注解配置声明式事务，作用于类上时所有public方法将具有该类型的事务属性
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)
public class AccountService2 {
    @Autowired
    private AccountDao accountDao;
    /*
     * 转账
     * @param id1 转出人id
     * @param id2 转入人id
     * @param price 金额
     */

    // 转出人减少余额
    public void transfer(int id1,int id2,double price){
        //获取查询到的用户
        Account account1 = accountDao.findById(id1);
        //转出金额
        account1.setBalance(account1.getBalance()-price);
        //更改用户
        accountDao.update(account1);

        /*此时没有事务管理，会造成张三的余额减少，
        而李四的余额并没有增加。所以事务处理位于业务层，
        即一个service方法是不能分割的。
        使用DataSourceTransactionManager事业管理器，能做到事业自动提交与回滚
        */
       //int i=1/0;//模拟程序出错

        // 转入人增加余额
        Account account2 = accountDao.findById(id2);
        account2.setBalance(account2.getBalance()+price);
        accountDao.update(account2);

    }

    //事务注解也可以只作用于单个方法
    @Transactional(isolation = Isolation.READ_UNCOMMITTED,readOnly = true)
    public Account findById(int id){
        return accountDao.findById(id);
    }
}
/*
事务：不可分割的原子操作。即一系列的操作要么同时成功，要么同时失败。

开发过程中，事务管理一般在service层，service层中可能会操作多次数据库，
这些操作是不可分割的。否则当程序报错时，可能会造成数据异常。

如：张三给李四转账时，需要两次操作数据库：张三存款减少、李四存款增加。
如果这两次数据库操作间出现异常，则会造成数据错误。*/

/*在Spring管理下不允许手动提交和回滚事务。此时我们需要使用Spring的事务管理方案，
在Spring框架中提供了两种事务管理方案：

编程式事务：通过编写代码实现事务管理。
声明式事务：基于AOP技术实现事务管理。
在Spring框架中，编程式事务管理很少使用，我们对声明式事务管理进行详细学习。

Spring的声明式事务管理在底层采用了AOP技术，其最大的优点在于无需通过编程的方式管理事务，
只需要在配置文件中进行相关的规则声明，就可以将事务规则应用到业务逻辑中。*/